package com.egao.common.module.pushInformation.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.wechat.WeChatUtils;
import com.egao.common.core.Constants;
import com.egao.common.core.RedisConstants;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.log.LogPushInformation;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.company.entity.Company;
import com.egao.common.module.company.service.CompanyService;
import com.egao.common.module.pushInformation.PushInformationConstants;
import com.egao.common.module.pushInformation.entity.PushInformation;
import com.egao.common.module.pushInformation.entity.PushInformationPosition;
import com.egao.common.module.pushInformation.entity.PushInformationPositionResult;
import com.egao.common.module.pushInformation.mapper.PushInformationMapper;
import com.egao.common.module.pushInformation.param.PushInformationParam;
import com.egao.common.module.pushInformation.service.PushInformationPositionResultService;
import com.egao.common.module.pushInformation.service.PushInformationPositionService;
import com.egao.common.module.pushInformation.service.PushInformationService;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.service.StudentService;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.service.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lym
 * @date 2024/8/23 10:30
 */
@Service
public class PushInformationServiceImpl extends ServiceImpl<PushInformationMapper, PushInformation> implements PushInformationService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private PushInformationPositionService pushInformationPositionService;
    @Resource
    private PushInformationPositionResultService pushInformationPositionResultService;
    @Resource
    private StudentService studentService;
    @Resource
    private CompanyService companyService;
    @Resource
    private DictService dictService;

    @Override
    public List<PushInformation> listPage(PageParam<PushInformationParam> pageParam) {
        return baseMapper.listPage(pageParam);
    }

    @Override
    public void save(Integer companyId, Integer category, Integer businessId, String title) {
        String position = stringRedisTemplate.opsForValue().get(RedisConstants.PUSH_POSITION_COMPANY_ID + companyId);
        String result = stringRedisTemplate.opsForValue().get(RedisConstants.PUSH_RESULT_COMPANY_ID + companyId);
        if (StrUtil.isBlank(position) || StrUtil.isBlank(result)) {
            LogPushInformation.error("没有查询到单位推荐信息缓存");
            return;
        }

        // 单位信息
        Company company = companyService.getById(companyId);
        String companyName = "";
        String companyArea = "";
        String companyNature = "";
        String companyIndustry = "";
        String companyScale = "";
        if (company != null) {
            companyName = company.getName();
            companyArea = company.getProvince() + " " + company.getCity();
            companyNature = dictService.cacheLabel(DictConstants.COMPANY_NATURE, company.getNature());
            companyIndustry = dictService.cacheLabel(DictConstants.COMPANY_INDUSTRY, company.getIndustry());
            companyScale = dictService.cacheLabel(DictConstants.COMPANY_SCALE, company.getScale());
        }

        // 学生和职位匹配度
        List<PushInformationPosition> positionList = JSONUtil.toList(position, PushInformationPosition.class);
        Map<Integer, List<PushInformationPosition>> positionMap = positionList.stream().collect(Collectors.groupingBy(PushInformationPosition::getStudentId));
        List<PushInformationPosition> pushInformationPositionList = new ArrayList<>();
        for (Map.Entry<Integer, List<PushInformationPosition>> item : positionMap.entrySet()) {
            Integer studentId = item.getKey();
            PushInformationPosition studentPushInformationPosition = item.getValue().stream().findFirst().orElse(null);
            if (studentPushInformationPosition == null) {
                continue;
            }

            PushInformation pushInformation = new PushInformation();
            pushInformation.setStudentId(studentId);
            pushInformation.setYearId(studentPushInformationPosition.getYear());
            pushInformation.setCompanyId(companyId);
            pushInformation.setCategory(category);
            pushInformation.setBusinessId(businessId);
            pushInformation.setTitle(title);
            pushInformation.setPushState(PushInformationConstants.PUSH_STATE_CHECK);
            pushInformation.setReadState(PushInformationConstants.READ_STATE_WAIT);
            pushInformation.setResumeState(PushInformationConstants.RESUME_STATE_WAIT);
            pushInformation.setXh(studentPushInformationPosition.getXh());
            pushInformation.setXm(studentPushInformationPosition.getXm());
            pushInformation.setCollegeName(studentPushInformationPosition.getCollegeName());
            pushInformation.setMajorName(studentPushInformationPosition.getMajorName());
            pushInformation.setCompanyName(companyName);
            pushInformation.setCompanyArea(companyArea);
            pushInformation.setCompanyNature(companyNature);
            pushInformation.setCompanyIndustry(companyIndustry);
            pushInformation.setCompanyScale(companyScale);

            if (baseMapper.insert(pushInformation) == 0) {
                throw new BusinessException("推荐信息保存失败");
            }

            item.getValue().forEach(d -> {
                PushInformationPosition pushInformationPosition = new PushInformationPosition();
                pushInformationPosition.setPushInformationId(pushInformation.getId());
                pushInformationPosition.setStudentId(d.getStudentId());
                pushInformationPosition.setPositionId(d.getPositionId());
                pushInformationPosition.setPositionName(d.getPositionName());
                pushInformationPosition.setMatching(d.getMatching());
                pushInformationPositionList.add(pushInformationPosition);
            });
        }
        if (!pushInformationPositionService.saveBatch(pushInformationPositionList)) {
            throw new BusinessException("推荐职位信息保存失败");
        }

        // 信息匹配结果
        List<PushInformationPositionResult> resultList = JSONUtil.toList(result, PushInformationPositionResult.class);
        resultList.forEach(d -> {
            d.setCompanyId(companyId);
            d.setCategory(category);
            d.setBusinessId(businessId);
        });
        if (!pushInformationPositionResultService.saveBatch(resultList)) {
            throw new BusinessException("推荐记录信息保存失败");
        }
    }

    @Override
    public boolean checkPushState(Integer category, Integer businessId) {
        PushInformation pushInformation = new PushInformation();
        pushInformation.setPushState(PushInformationConstants.PUSH_STATE_WAIT);
        int result = baseMapper.update(pushInformation, new LambdaUpdateWrapper<PushInformation>()
                .eq(PushInformation::getCategory, category)
                .eq(PushInformation::getBusinessId, businessId)
        );
        return result > 0;
    }

    @Override
    public void push() {
        List<PushInformation> pushInformationList = baseMapper.selectList(new LambdaQueryWrapper<PushInformation>()
                .eq(PushInformation::getPushState, PushInformationConstants.PUSH_STATE_WAIT)
        );
        if (CollectionUtil.isEmpty(pushInformationList)) {
            return;
        }

        List<Integer> studentIdList = pushInformationList.stream().map(PushInformation::getStudentId).distinct().collect(Collectors.toList());
        List<Student> studentList = studentService.list(new LambdaQueryWrapper<Student>()
                .select(Student::getId, Student::getXh)
                .in(Student::getId, studentIdList)
        );

        // 更新推送状态
        List<PushInformation> updateList = new ArrayList<>();
        for (PushInformation pushInformation : pushInformationList) {
            PushInformation update = new PushInformation();
            update.setId(pushInformation.getId());
            update.setPushState(PushInformationConstants.PUSH_STATE_SUCCESS);
            update.setPushTime(new Date());
            updateList.add(update);
        }
        if (!updateBatchById(updateList)) {
            LogPushInformation.error("批量更新推送状态失败");
            return;
        }

        LogPushInformation.info(StrUtil.format("{}推送就业信息{}条给{}个学生",
                DateUtil.today(), pushInformationList.size(), studentList.size()));

        for (Student student : studentList) {
            List<PushInformation> list = pushInformationList.stream().filter(d -> student.getId().equals(d.getStudentId())).collect(Collectors.toList());

            StrBuilder builder = StrBuilder.create();
            builder.append("<a href='" + PushInformationConstants.ENTERPRISES_WECHAT__URL + "'>");
            builder.append("就业指导服务中心：<br>");
            builder.append("亲爱的同学，根据您的专业及就业意向等，现向您推荐").append(list.size()).append("条就业信息。<br>");
            for (int i = 0; i < list.size(); i++) {
                if (i == 3) {
                    builder.append("更多信息请点击后查看");
                    break;
                }
                String title = StrUtil.sub(list.get(i).getTitle(), 0, 13);
                builder.append(title).append("...<br>");
            }
            builder.append("</a><br>");
            builder.append(DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN));
            String[] xh = {student.getXh()};
            JsonResult jsonResult = WeChatUtils.push(xh, builder.toString());
            if (Constants.RESULT_ERROR_CODE == jsonResult.getCode()) {
                LogPushInformation.error(StrUtil.format("推送信息推送失败,学号:{},错误信息:{}", xh, jsonResult.getMsg()));
            }
        }
    }
}
